<template>
	<view class="helang-multi-selector">
		<view class="shade" :style="{'z-index':zIndex}" @click="cancel" @touchmove.stop.prevent="pageModal"></view>
		<view class="popup" :style="{'z-index':zIndex+1}">
			<view class="flex action-bar">
				<view class="cancel" @click="cancel">取消</view>
				<view class="confirm" @click="confirm">确定</view>
			</view>
			<view style="padding: 0 16rpx;">
				<view v-if="selectedValues.length > 0" class="selected-container">
					<text style="color: #666666;">已选择：</text>
					<text 
						v-for="(item,index) in selectedValues" 
						:key="index"
						@click="handleSelectedClick(index)"
					>
						<text v-if="index > 0"> - </text>
						<text style="cursor: pointer;">{{item.label}}</text>
					</text>
				</view>
				<view class="select flex" :style="translateX">
					<scroll-view class="select-col" 
						v-for="(col,colIndex) in props.list" 
						:key="colIndex"
						:class="[selectItemWidth,{'loading':props.loadingIndex === colIndex}]" 
						scroll-y
						:scroll-into-view="defaultScrollInfoView[colIndex]"
					>
						<view class="select-item flex flex-conter" 
							v-for="(item,index) in col" 
							:key="item.value"
							:id="cid+colIndex+'_'+index" 
							@click="handleItemClick(colIndex,index)"
						>
							<view class="content ellipsis">{{item.label}}</view>
							<view class="checked" :class="{ 'show': checkedIndexs[colIndex] === index }">
								<!-- 小程序中插槽存在问题，不能在循环中使用 -->
								<!-- #ifdef H5 || APP-PLUS -->
								<slot name="checked"></slot>
								<view class="checked-default flex flex-conter" v-if="!$slots.checked"></view>
								<!-- #endif -->
								<!-- #ifndef H5 || APP-PLUS -->
								<view class="checked-default flex flex-conter"></view>
								<!-- #endif -->
							</view>
						</view>
					</scroll-view>
				</view>
			</view>
		</view>
	</view>
</template>

<script setup>
	import { ref, computed, onMounted } from 'vue';
	
	const props = defineProps({
		list: {
			type: Array,
			default: []
		},
		zIndex: {
			type: Number,
			default: 100
		},
		loadingIndex: {
			type: Number,
			default: -1
		},
		defaultIndexs: {
			type: Array,
			default: []
		}
	});
	// 
	const emit = defineEmits(['change','cancel','confirm']);
	
	// 组件id
	const cid = ref(`h_${parseInt(Math.random()*100000,10)}_${parseInt(Math.random()*10000,10)}_`);
	
	// 组件显示层级
	const zIndex = ref(props.zIndex || 100);
	// 选中索引
	const checkedIndexs = ref([]);
	// 默认 scrollView 元素滚动位置
	const defaultScrollInfoView = ref([]);
	
	// 选项宽度
	const selectItemWidth = computed(() => {
	  if(props.list.length >= 3){
		  return 'col-3';
	  }
	  if(props.list.length == 2){
		  return 'col-2';
	  }
	  return '';
	})
	
	// X轴偏移
	const translateX = computed(() => {
	  if(props.list.length > 3){
		  return `transform: translateX(-${(props.list.length-3)*0.3333333*100}%)`;
	  }
	  return `transform: translateX(0)`;
	})
	
	// 选项宽度
	const selectedValues = computed(() => {
	  let values = [];
	  // 不使用map，有存在取不到值得异常情况
	  checkedIndexs.value.forEach((item,index)=>{
		const temp = props.list[index];
		if(temp){
			values.push(temp[item]);
		}
	  });
	  return values;
	})
	
	// 默认挂在后执行
	onMounted(()=>{
		// 同步默认选中信息
		checkedIndexs.value = props.defaultIndexs;
		
		handleScrollInfoView(props.defaultIndexs);
	})
	
	// 改变事件
	const change = (colIndex) => {
		const indexs = checkedIndexs.value;
		const values =  selectedValues.value;
				
		emit('change', {
			colIndex,
			indexs,
			values
		});
	};
	
	// 取消事件
	const cancel = ()=>{
		emit('cancel')
	}
	
	// 确认事件
	const confirm = ()=>{
		const indexs = checkedIndexs.value;
		const values =  selectedValues.value;
		
		emit('confirm',{
			indexs,
			values
		});
	}
	
	// 处理选择列表项点击
	const handleItemClick = (colIndex,index)=>{
		// loading状态中不响应点击事件
		if(props.loadingIndex >= 0){
			return;
		}
		// 筛选当前点击列之前的数据，后面的列数据销毁
		let indexs = checkedIndexs.value.filter((item,index)=>{
			return index <= colIndex;
		})
		indexs[colIndex] = index;
		// 追加本次点击列的选中行
		checkedIndexs.value = [...indexs];
		change(colIndex);
	}
	
	// 处理已选数据的点击
	const handleSelectedClick = (colIndex)=>{
		const index = checkedIndexs.value[colIndex];
		handleItemClick(colIndex,index)
	}
	
	// 页面模态化(禁止弹窗后触摸滚动)
	const pageModal = ()=>{
		
	}
	
	// 重置scrollView显示元素位置
	const handleScrollInfoView = async (indexs)=>{
		// 不延迟调用会出现设置不生效的BUG
		await utilWait();
		defaultScrollInfoView.value = indexs.map((item,index)=>{
			return `${cid.value}${index}_${item-2}`;
		})
	}
	
	// 延迟工具函数
	const utilWait = (time = 10) => {
		return new Promise((y) => {
			setTimeout(() => {
				y();
			}, time);
		})
	}
	
</script>

<style lang="scss">
	@mixin lineStyle{
		content: '';
		display: block;
		position: absolute;
		height: 1px;
		background-color: #e3e3e3;
		transform: scaleY(0.5);
		bottom: 0;
		left: 0;
		right: 0;
		width: auto;
	}
	
	.helang-multi-selector{
		user-select: none;
		font-size: 28rpx;
		color: #333333;
		
		.ellipsis {
		  overflow: hidden;
		  white-space: nowrap;
		  text-overflow: ellipsis;
		}
		
		.flex{
			display: flex;
			flex-direction: row;
			flex-wrap: nowrap;
			align-content: flex-start;
			justify-content: flex-start;
			align-items: flex-start;
			
			&-conter{
				align-content: center;
				align-items: center;
			}
		}
		.shade{
			position: fixed;
			height: 100%;
			width: 100%;
			left: 0;
			background-color: rgba(0, 0, 0, 0.45);
			top: 0;
		}
		.popup{
			position: fixed;
			width: 100%;
			height: auto;
			left: 0;
			background-color: #ffffff;
			overflow: hidden;
			bottom: 0;
			
			&::after{
				content: '';
				display: block;
				width: 100%;
				height: 0;
				height: env(safe-area-inset-bottom);
			}
			
			
			.action-bar{
				position: relative;
				justify-content: space-between;
				
				&::after{
					@include lineStyle();
				}
				
				.cancel, .confirm{
					padding: 24rpx 16rpx;
					font-size: 28rpx;
				}
				
				.cancel{
					color: #666666;
				}
				
				.confirm{
					color: #007aff;
				}
			}
			
			.selected-container{
				font-size: 32rpx;
				color: #333333;
				padding: 16rpx 0;
				position: relative;
				
				&::after{
					@include lineStyle();
				}
			}
		}
		.select {
			transform: translateX(0);
			transition: transform 0.3s ease 0s;
			
			&-col{
				transition: width 0.3s ease 0s;
				width: 100%;
				flex-shrink: 0;
				height: 220px;
				
				&.col-2{
					width: 50%;
				}
				
				&.col-3{
					width: 33.33333%;
				}
				
				&.loading{
					position: relative;
					
					&::after,&::before{
						content: '';
						position: absolute;
						left: 0;
						top: 0;
						bottom: 0;
						right: 0;
						box-sizing: border-box;
					}
					
					&:before{
						z-index: 10;
						height: auto;
						width: auto;
						background-color: rgba(255, 255, 255, 0.75);
						backdrop-filter: 0.5;
					}
					
					&::after{
						z-index: 11;
						margin: auto;
						width: 50rpx;
						height: 50rpx;
						border-radius: 50%;
						border: #d6d6d6 solid 2px;
						border-top-color: transparent;
						animation: loading 1s linear 0s infinite normal;
					}
				}
			}
			
			&-item{
				padding: 8rpx 16rpx;
				box-sizing: border-box;
				min-height: 80rpx;
				position: relative;
				
				&:active{
					background-color: #f6f6f6
				}
				
				&::after{
					@include lineStyle();
					left: 16rpx;
					right: 16rpx;
				}
			}
			
			.content{
				width: 0;
				flex: 1 0 auto;
			}
			.checked{
				margin-left: 4px;
				display: none;
				
				&-default{
					width: 36rpx;
					height: 60rpx;
					justify-content: center;
					
					&::before{
						content: '';
						display: block;
						width: 16rpx;
						height: 30rpx;
						border-bottom: #666 solid 3px;
						border-right: #666 solid 3px;
						border-radius: 2px;
						box-sizing: border-box;
						transform: rotate(45deg);
						margin-bottom: 4rpx;
					}
				}
				
				&.show{
					display: block;
				}
			}
		}
	}
	
	@keyframes loading{
		from{
			transform: rotate(0deg);
		}
		to{
			transform: rotate(360deg);
		}
	}
</style>